﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace ESpace
{
    class EMath
    {
        static public double Sin(double x)
        {
            return Math.Sin((x / 180.0) * Math.PI);
        }
        //---------------------------------------------------------------------------
        static public double Cos(double x)
        {
            return Math.Cos((x / 180.0) * Math.PI);
        }
        //---------------------------------------------------------------------------
        static public double Tan(double x)
        {
            return Math.Tan((x / 180.0) * Math.PI);
        }
        //---------------------------------------------------------------------------
        static public double ASin360(double x, bool right, bool up)
        {
            double result = Math.Asin(x) * 180.0 / Math.PI;
            if (right) return 180.0 - result;
            else if (up) return 360.0 + result;
            return result;
        }
        //---------------------------------------------------------------------------

        static public double ASin(double x)
        {
            return Math.Asin(x) * 180.0 / Math.PI;
        }
        //---------------------------------------------------------------------------

        static public double ACos(double x)
        {
            return Math.Acos(x) * 180.0 / Math.PI; 
        }
        //---------------------------------------------------------------------------
        static public double ATan(double x)
        {
            return Math.Atan(x) * 180.0 / Math.PI;
        }

        //---------------------------------------------------------------------------

        static public double ACos360(double x, bool up)
        {
            double result = Math.Acos(x) * 180.0 / Math.PI;
            if (up) return 360.0 - result;
            return result;
        }
        
        //---------------------------------------------------------------------------
        static public double Hyp(double Katet1, double Katet2)
        {
            return Math.Sqrt(Math.Pow(Katet1, 2.0) + Math.Pow(Katet2, 2.0));
        }
        //---------------------------------------------------------------------------

        static public double Ktt(double Hypotenuse, double Katet)
        {
            return Math.Sqrt(Math.Pow(Hypotenuse, 2.0) - Math.Pow(Katet, 2.0));
        }
        //---------------------------------------------------------------------------
        static public double UgolProt(double hip, double protKat)
        {
            return ASin(protKat / hip);
        }
        //---------------------------------------------------------------------------
        static public double UgolPril(double hip, double prilKat)
        {
            return ACos(prilKat / hip);
        }
        //---------------------------------------------------------------------------
        static public double UgolKtt(double prilKat, double protKat)
        {
            return ATan(protKat / prilKat);
        }
        //---------------------------------------------------------------------------
        static public double GetAngle(double x1, double y1, double x2, double y2)
        {
            if (y2 == y1) { if (x2 >= x1) return 0; else return 180; }
            if (x2 == x1) { if (y2 >= y1) return 90; else return 270; }

            double ret = ATan((y2 - y1) / (x2 - x1));
            if (ret < 0) ret += 180;
            if (y2 < y1) ret += 180;
            return ret;
        }
        //---------------------------------------------------------------------------
        public struct aT // стороны треугольника
        {
            public double a; //угол точки A
            public double b; //угол точки B
            public double c; //угол точки C
        }
        //---------------------------------------------------------------------------
        public static aT AnglesTriangle(Point A, Point B, Point C)
        {
            double x;
            double y;
            // стороны
            x = Math.Abs(B.X - C.X);
            y = Math.Abs(B.Y - C.Y);
            double a = EMath.Hyp(x, y);

            x = Math.Abs(A.X - C.X);
            y = Math.Abs(A.Y - C.Y);
            double b = EMath.Hyp(x, y);

            x = Math.Abs(A.X - B.X);
            y = Math.Abs(A.Y - B.Y);
            double c = EMath.Hyp(x, y);

            aT res = new aT();

            res.a = AnglesTriangleA(a, b, c);
            res.b = AnglesTriangleA(b, a, c);
            res.c = AnglesTriangleA(c, a, b);

            return res;
        }
        //---------------------------------------------------------------------------
        public static double AnglesTriangleA(double a, double b, double c)
        {
            return EMath.ACos((b * b + c * c - a * a) / (2.0 * b * c));
        }
        //---------------------------------------------------------------------------
        public static double AnglesTriangleA(Point A, Point B, Point C)
        {
            double x;
            double y;
            // стороны
            x = Math.Abs(B.X - C.X);
            y = Math.Abs(B.Y - C.Y);
            double a = EMath.Hyp(x, y);

            x = Math.Abs(A.X - C.X);
            y = Math.Abs(A.Y - C.Y);
            double b = EMath.Hyp(x, y);

            x = Math.Abs(A.X - B.X);
            y = Math.Abs(A.Y - B.Y);
            double c = EMath.Hyp(x, y);

            return AnglesTriangleA(a, b, c);
        }
        //---------------------------------------------------------------------------
        public static double AngleOnXClockwise(Point p1, Point p2)
        {
            double x = p2.X - p1.X;
            double y = p2.Y - p1.Y;
            return ACos360(x / Hyp(x, y),(y<0));
        }

        //---------------------------------------------------------------------------
        
        static public System.Drawing.Point OtnCoord(System.Drawing.Point ZeroPoint, System.Drawing.Point shift, double angle)
        {
            System.Drawing.Point p = new System.Drawing.Point();

            //*** оптимизация **************************
            if (angle == 0)
            {
                p.X = ZeroPoint.X + shift.X;
                p.Y = ZeroPoint.Y + shift.Y;
                return p;
            }
            if (angle == 90)
            {
                p.X = ZeroPoint.X + shift.Y;
                p.Y = ZeroPoint.Y + shift.X;
                return p;
            }
            if (angle == 180)
            {
                p.X = ZeroPoint.X - shift.X;
                p.Y = ZeroPoint.Y - shift.Y;
                return p;
            }
            if (angle == 270)
            {
                p.X = ZeroPoint.X - shift.Y;
                p.Y = ZeroPoint.Y - shift.X;
                return p;
            }
            //end*** оптимизация ***********************

            // длина
            double l = Hyp(shift.X, shift.Y);
            // угол направления
            double a = angle;
            if (shift.Y > 0) a += ACos(shift.X / l);
            if (shift.Y < 0) a += ACos360(shift.X / l, true);
            p.X = (int)(ZeroPoint.X + l * Cos(a));
            p.Y = (int)(ZeroPoint.Y + l * Sin(a));
            return p;
        }
        //---------------------------------------------------------------------------

    }
}
